package chenji.StrongFossil.Config;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

import org.bukkit.Material;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import chenji.StrongFossil.Main;
import chenji.StrongFossil.Puncher.Puncher;
import chenji.StrongFossil.Fossil.PuncherFossil.PunchFossil;
import chenji.StrongFossil.Fossil.PuncherFossil.PuncherStrongType;

public class StrongFossilConfig {

	FileConfiguration config;

	final File configFile = new File(Main.getDataFile() + "/config.yml");

	public void saveConfig() {
		try {
			config.save(configFile);
			loadConfig();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void reloadConfig() {
		this.loadPunchFossil();
		this.loadPuncher();
		this.loadMaps();
		this.loadOpinitons();
	}

	private void loadOpinitons() {
		boolean EnableBroken = config.getBoolean("Punch.EnableBroken");
		boolean EnableChance = config.getBoolean("Punch.EnableChance");
		double DefaultChance = config.getDouble("Punch.DefaultChance");
		String EmptyPunchName = config.getString("Punch.EmptyPunchName");
		if (EmptyPunchName == null) {
			Main.getLog().warning("EmptyPunchName节点不可以为空值，已经自动按照默认值读取(&c[空位])");
			EmptyPunchName = "&c[空位]";
		}
		boolean ArrowOtherLore = config.getBoolean("Punch.ArrowOtherLore");
		List<String> LimitLoreList = config.getStringList("Punch.LimitLoreList");
		Main.installPunchManager(EnableBroken, EnableChance, DefaultChance, EmptyPunchName, ArrowOtherLore,
				LimitLoreList);
	}

	private void loadMaps() {
		HashMap<Material, Integer> PunchList = this.getMaterialIntegerList("Punch.PunchList", false);
		HashMap<Material, Double> LevelChance = this.getMaterialList("Punch.LevelChance", false);
		HashMap<Material, Double> BrokeStartChance = this.getMaterialList("Punch.BrokeStartChance", false);
		HashMap<Material, Double> BrokeLevelAdd = this.getMaterialList("Punch.BrokeLevelAdd", false);
		Main.InitializePunchManager(PunchList, LevelChance, BrokeStartChance, BrokeLevelAdd);
	}

	public void loadPuncher() {
		ArrayList<String> KeyList = new ArrayList<String>();
		for (String s : config.getKeys(true)) {
			if (s.startsWith("Punch.Puncher.")) {
				if (s.replaceAll("Punch.Puncher.", "").contains(".")) {
					continue;
				}
				KeyList.add(s);
			}
		}
		int i = 0;
		HashSet<Puncher> set = new HashSet<Puncher>();
		for (String Path : KeyList) {
			ItemStack item = getItemStack(Path);
			if (item == null) {
				Main.getLog().warning("物品" + Path.replaceAll("Punch.PunchChance.", "") + "未能加载");
				continue;
			}
			int Durable = config.getInt(Path + "." + "Durable");
			double addChange = config.getDouble(Path + "." + "AddChance");
			set.add(new Puncher(item, Durable, addChange));
			i++;
		}
		if (i == 0) {
			Main.getLog().info("没有加载任何打开钻头");
		} else {
			Main.getLog().info("共加载" + i + "个打孔钻头");
		}
		Main.InitializePuncherManager(set);

	}

	public void loadConfig() {
		try {
			config = new YamlConfiguration();
			config.load(configFile);
			reloadConfig();
			if (!(version())) {
				saveDefaultConfig();
				Main.getLog().warning("config版本错误，现在已经自动创建默认配置。");
			}
		} catch (FileNotFoundException ex) {
			Main.getLog().warning("config未找到，现在已经自动创建默认配置。");
			saveDefaultConfig();

		} catch (InvalidConfigurationException e) {
			Main.getLog().warning("config无效，现在已经自动创建默认配置。");
			saveDefaultConfig();
		} catch (IOException e) {
			Main.getLog().warning("加载config时出现未知错误。");
			e.printStackTrace();
		}

	}

	public void saveDefaultConfig() {
		InputStream i = null;
		try {
			URL url = getClass().getResource("/config.yml");
			URLConnection connection;
			connection = url.openConnection();
			connection.setUseCaches(false);
			i = connection.getInputStream();
			saveFile(configFile, i);
			config.load(configFile);
			reloadConfig();
		} catch (IOException | InvalidConfigurationException e) {
			e.printStackTrace();
		} finally {
			try {
				i.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public File saveFile(File file, InputStream is) {
		OutputStream os = null;
		try {
			os = new FileOutputStream(file);
			byte buffer[] = new byte[4 * 1024];
			int len = 0;
			while ((len = is.read(buffer)) != -1) {
				os.write(buffer, 0, len);
			}
			os.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return file;
	}

	public StrongFossilConfig() {
		loadConfig();
	}

	public boolean version() {
		if (config.contains("version")) {
			double s = config.getDouble("version");
			if (s == 1.0) {
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	public Material getMaterial(String material) {
		if (material == null) {
			return null;
		}
		Material m;
		try {
			m = Enum.valueOf(Material.class, material);
		} catch (Exception e) {
			return null;
		}
		return m;

	}

	public List<String> transiateColorCode(List<String> s) {
		List<String> rt = new ArrayList<String>();
		for (String d : s) {

			rt.add(d.replaceAll("&", "§"));
		}
		return rt;
	}

	public HashMap<Material, Double> getMaterialList(String Path, boolean AllowZero) {
		ArrayList<String> list = new ArrayList<String>();
		for (String s : config.getKeys(true)) {
			if (s.startsWith(Path + ".")) {
				if (s.replaceAll(Path + ".", "").contains(".")) {
					continue;
				}
				list.add(getLastNodeName(s));
				System.out.println(s);
			}
		}
		HashMap<Material, Double> map = new HashMap<Material, Double>();
		for (String s : list) {
			Material m = this.getMaterial(s);
			if (m == null) {
				Main.getLog().warning(this.getLastNodeName(Path) + "下的" + s + "不是一个有效的物品材质名称。");
				continue;
			}
			double i = config.getDouble(Path + "." + s);
			if (!(AllowZero)) {
				Main.getLog().warning(this.getLastNodeName(Path) + "下的" + s + "节点不能填写0或不填。");
				continue;
			}
			map.put(m, i);

		}
		return map;
	}

	public HashMap<Material, Integer> getMaterialIntegerList(String Path, boolean AllowZero) {
		ArrayList<String> list = new ArrayList<String>();
		for (String s : config.getKeys(true)) {
			if (s.startsWith(Path + ".")) {
				if (s.replaceAll(Path + ".", "").contains(".")) {
					continue;
				}
				list.add(getLastNodeName(s));
			}
		}
		HashMap<Material, Integer> map = new HashMap<Material, Integer>();
		for (String s : list) {
			Material m = this.getMaterial(s);
			if (m == null) {
				Main.getLog().warning(this.getLastNodeName(Path) + "下的" + s + "不是一个有效的物品材质名称。");
				continue;
			}
			int i = config.getInt(Path + "." + s);
			System.out.println(Path + "." + s);
			if (!(AllowZero)) {
				if (i == 0) {
					Main.getLog().warning(this.getLastNodeName(Path) + "下的" + s + "节点不能填写0或不填。");
					continue;
				}
			}
			map.put(m, i);

		}
		return map;
	}

	public String getLastNodeName(String Path) {
		String[] s = Path.split("\\.");
		if (s.length == 0) {
			return null;
		}
		return s[s.length - 1];
	}

	public void loadPunchFossil() {
		ArrayList<String> KeyList = new ArrayList<String>();
		for (String s : config.getKeys(true)) {
			if (s.startsWith("Punch.PunchChance.")) {
				if (s.replaceAll("Punch.PunchChance.", "").contains(".")) {
					continue;
				}
				KeyList.add(s);
			}

		}
		int i = 0;
		HashSet<PunchFossil> set = new HashSet<PunchFossil>();
		for (String s : KeyList) {
			ItemStack item = getItemStack(s);

			if (item == null) {
				Main.getLog().warning("物品" + s.replaceAll("Punch.PunchChance.", "") + "未能加载");
				continue;
			}
			PuncherStrongType type = null;
			if (config.contains(s + ".StrongPoint") && config.getString(s + ".StrongPoint") != null) {
				String StrongPoint = config.getString(s + ".StrongPoint");
				if (StrongPoint.equals("Improve")) {
					type = PuncherStrongType.Improve;
				}
				if (StrongPoint.equals("Protect")) {
					type = PuncherStrongType.Protect;
				}
			} else {
				Main.getLog().warning("物品" + s.replaceAll("Punch.PunchChance.", "") + "未能加载,未找到StrongPoint节点");
				continue;
			}
			if (type == null) {
				Main.getLog().warning("物品" + s.replaceAll("Punch.PunchChance.", "") + "未能加载,StrongPoint节点不是一个有效的节点。");
				continue;
			}
			double value;
			if (config.contains(s + ".Value")) {
				value = config.getDouble(s + ".Value");

			} else {
				Main.getLog().warning("物品" + s.replaceAll("Punch.PunchChance.", "") + "未能加载,未找到Value节点");
				continue;
			}
			PunchFossil pf = new PunchFossil(item, type, value);
			set.add(pf);
			i++;
		}
		if (i == 0) {
			Main.getLog().info("没有加载任何打孔强化石");
		} else {
			Main.getLog().info("共加载" + i + "个打孔强化石");
		}
		Main.InitializePunchFossilManager(set);

	}

	public ItemStack getItemStack(String path) {
		String material = this.config.getString(path + ".Material");
		Material m = this.getMaterial(material);
		if (m == null) {

			Main.getLog().warning("未知的物品类型" + material);
			return null;
		}
		short data = 0;

		if (this.config.contains(path + ".data")) {
			try {
				data = (short) this.config.getInt(path + ".data");
			} catch (Exception e) {
				data = 0;
			}
		}
		ItemStack i;
		if (data != 0) {
			i = new ItemStack(m);
		} else {
			i = new ItemStack(m, 1, data);
		}
		ItemMeta meta = i.getItemMeta();
		if (config.contains(path + ".Subject") && config.getString(path + ".Subject") != null) {
			meta.setDisplayName(config.getString(path + ".Subject").replaceAll("&", "§"));
		} else {
			meta.setDisplayName("空值");
		}

		if (config.contains(path + ".Lore") && config.getStringList(path + ".Lore") != null) {
			meta.setLore(this.transiateColorCode(config.getStringList(path + ".Lore")));
		}
		i.setItemMeta(meta);
		return i;

	}
}